/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_KEKE_IMAGE_DATA_CACHE_INTERNAL_H
#define IMAGE_KNIFE_C_KEKE_IMAGE_DATA_CACHE_INTERNAL_H

#include <memory>
#include <multimedia/image_framework/image/pixelmap_native.h>
#include <arkui/native_type.h>
#include "file_type_parser.h"
#include "imageknife_option.h"
#include "imageknife_type.h"
#include "image_data_cache.h"
#include "image_data.h"
#include "utils/pixelmap_utils.h"
#include "log.h"

namespace ImageKnifePro {
struct ImageDataCacheInternal : ImageDataCache {
public:
    // 原始图片宽度
    uint32_t imageWidth = 0;
    // 原始图片高度
    uint32_t imageHeight = 0;
    // 图片编码类型：jpg,png,gif,webp,etc
    ImageFormat type = ImageFormat::UNKNOWN;
    // 图片的原请求类型
    ImageRequestType requestType = ImageRequestType::MAIN_SRC;

    uint32_t GetImageWidth() const override
    {
        return imageWidth;
    }

    uint32_t GetImageHeight() const override
    {
        return imageHeight;
    }

    uint32_t GetImageCacheSize() const override
    {
        return cacheSize_;
    }

    Image_Size GetPixelmapSize() const
    {
        return pixelmapSize_;
    }

    ImageFormat GetImageFormat() const override
    {
        return type;
    }

    std::shared_ptr<uint8_t[]> GetFileBuffer() const;
    std::shared_ptr<ImageKnifeOption> GetImageKnifeOption() const;
    void SetDesiredSize(Image_Size desiredSize);
    /**
     * @brief 获取动图逐帧模式对应的每帧播放时长数组
     * @return 返回播放时长数组，单位ms
     * 动图批量解码模式的cache调用则返回nullptr，批量解码获取时长数组需先获取ImageData
     */
    int *GetAnimationDelayTimeList() const;

    std::shared_ptr<FileTypeInfo> GetFileTypeInfo() const;
    // 判断DecodeImageSource的来源
    bool IsDefaultDecodeSource() const;

    explicit ImageDataCacheInternal(const char *base64) : base64_(base64)
    {
    }

    explicit ImageDataCacheInternal(OH_PixelmapNative *pixelmap)
        : frameCount_(1)
    {
        imageDesc_ = new ArkUI_DrawableDescriptor *[frameCount_];
        if (pixelmap != nullptr) {
            imageDesc_[0] = OH_ArkUI_DrawableDescriptor_CreateFromPixelMap(pixelmap);
            cacheSize_ = GetPixelmapCacheSize(pixelmap);
            imageData_ = std::make_shared<ImageData>(pixelmap);
        } else {
            imageDesc_[0] = nullptr;
            IMAGE_KNIFE_LOG(LOG_ERROR, "Create DataCache With Null Pixelmap");
        }
    }

    ImageDataCacheInternal(std::shared_ptr<uint8_t[]> buffer, uint32_t bufferLength, bool isDefaultDecodeSource,
                           std::shared_ptr<ImageKnifeOption> option, std::shared_ptr<FileTypeInfo> fileTypeInfo);

    ImageDataCacheInternal(std::shared_ptr<ImageData> data, bool isAnimator)
    {
        IMAGE_KNIFE_CHECK(data == nullptr);
        imageData_ = data;
        frameCount_ = data->GetFrameCount();
        IMAGE_KNIFE_CHECK(frameCount_ <= 0);
        OH_PixelmapNative **pixelmapList = data->GetPixelmapList();
        IMAGE_KNIFE_CHECK(pixelmapList == nullptr);
        int *delayList = data->GetDelayTimeList();

        if (isAnimator) {
            frameInfoList_ = new ArkUI_ImageAnimatorFrameInfo *[frameCount_];
        }

        const int defaultDelayTime = 100;
        imageDesc_ = new ArkUI_DrawableDescriptor *[frameCount_];
        for (int i = 0; i < frameCount_; i++) {
            ArkUI_DrawableDescriptor *imgDesc = nullptr;
            if (pixelmapList[i] != nullptr) {
                cacheSize_ += GetPixelmapCacheSize(pixelmapList[i]);
                imgDesc = OH_ArkUI_DrawableDescriptor_CreateFromPixelMap(pixelmapList[i]);
            } else {
                IMAGE_KNIFE_LOG(LOG_WARN, "Create DataCache, Pixelmap is null at frame:%{public}d", i);
            }
            imageDesc_[i] = imgDesc;

            if (isAnimator) {
                frameInfoList_[i] =  OH_ArkUI_ImageAnimatorFrameInfo_CreateFromDrawableDescriptor(imgDesc);
                int delayTime = delayList == nullptr ? defaultDelayTime :
                    (delayList[i] > 0 ? delayList[i] : defaultDelayTime);
                OH_ArkUI_ImageAnimatorFrameInfo_SetDuration(frameInfoList_[i], delayTime);
            }
        }
    }

    const char *GetBase64() const
    {
        return base64_;
    }

    ArkUI_DrawableDescriptor *GetDrawableDescriptor() const
    {
        if (imageDesc_ == nullptr) {
            return nullptr;
        }
        return imageDesc_[0];
    }

    ArkUI_DrawableDescriptor **GetDrawableDescriptorList() const
    {
        return imageDesc_;
    }

    ArkUI_ImageAnimatorFrameInfo **GetFrameInfoList() const
    {
        return frameInfoList_;
    }

    uint32_t GetFrameCount() const
    {
        return frameCount_;
    }

    std::shared_ptr<ImageData> GetImageData() const
    {
        return imageData_;
    }

    ~ImageDataCacheInternal() override
    {
        if (base64_ != nullptr) {
            delete [] base64_;
        }

        if (frameInfoList_ != nullptr) {
            for (int i = 0; i < frameCount_; i++) {
                OH_ArkUI_ImageAnimatorFrameInfo_Dispose(frameInfoList_[i]);
            }
            delete [] frameInfoList_;
        }

        if (imageDesc_ != nullptr) {
            for (int i = 0; i < frameCount_; i++) {
                OH_ArkUI_DrawableDescriptor_Dispose(imageDesc_[i]);
            }
        }
    }
private:
    Image_Size pixelmapSize_ = {0, 0};
    // 缓存所消耗的字节数，比实际的有所误差
    uint32_t cacheSize_ = 0;
    // base64 编码string 用于Image组件简单显示动图
    const char *base64_ = nullptr;
    // 动图 FrameInfo 数组
    ArkUI_ImageAnimatorFrameInfo **frameInfoList_ = nullptr;
    // 动图帧数
    uint32_t frameCount_ = 0;
    // 动图逐帧解码模式所需的文件buffer
    std::shared_ptr<uint8_t[]> fileBuffer_ = nullptr;
    // 动图描述图片解码，变换方式的option，决定最终图片pixelmap内容
    std::shared_ptr<ImageKnifeOption> option_ = nullptr;
    // 动图逐帧解码模式，辅助解码的文件信息描述
    std::shared_ptr<FileTypeInfo> fileTypeInfo_ = nullptr;
    // 图片可写描述符
    ArkUI_DrawableDescriptor **imageDesc_ = nullptr;
    // 图片pixelmap或动图批量解码的pixelmapList
    std::shared_ptr<ImageData> imageData_ = nullptr;

    bool isDefaultDecodeSource_ = false;

    uint32_t GetPixelmapCacheSize(OH_PixelmapNative *pixelmap);
};

}

#endif // IMAGE_KNIFE_C_KEKE_IMAGE_DATA_CACHE_INTERNAL_H
